#include "Camera.h"

#include <Math.h>

#define PI 3.1415

Camera::Camera()
{
	rotationX = 0;
	rotationY = 0;
	for(int i = 0; i<3; i++)
	{
		lookAt[i]		= 0;
		up[i]			= 0;
		translation[i]	= 0;
		lookAtPoint[i]  = 0;
	}
	up[1] = 1;
	bool lockOn = true;
}
void Camera::calculateLookAt()
{
	lookAt[0] = lookAtPoint[0] - translation[0];
	lookAt[1] = lookAtPoint[1] - translation[1];
	lookAt[2] = lookAtPoint[2] - translation[2];

	float magnitude = sqrtf(lookAt[0] * lookAt[0] + lookAt[1] * lookAt[1] + lookAt[2] * lookAt[2]);
	lookAt[0] /= magnitude;
	lookAt[1] /= magnitude;
	lookAt[2] /= magnitude;
}

void Camera::calculateTranslation()
{

	//Proper:
	//theta refers to rotation about the X-axis and is limited to 180 degrees
	//gamma refers to rotation about the Y-axis and is limited to 360 degrees
	//x = radius * sin(theta) * cos(gamma)
	//y = radius * sin(theta) * sin(gamma)
	//z = radius * cos(theta)

	if(rotationY < 0.1)
	{
		rotationY = 0.1;
	}
	else if (rotationY > 90)
	{
		rotationY = 90;
	}

	if(rotationX < -360 || rotationX > 360)
	{
		rotationX = 0.0;
	}

	double theta = rotationY*PI/180;
	double gamma = rotationX*PI/180;

	translation[0] = (radiusOffset + radiusOffsetNew) * sin(theta) * cos(gamma) + lookAtPoint[0];	
	translation[2] = (radiusOffset + radiusOffsetNew) * sin(theta) * sin(gamma) + lookAtPoint[2];
	translation[1] = (radiusOffset + radiusOffsetNew) * cos(theta) + lookAtPoint[1];
	//translation[2] = radiusOffset * cos(angleRotation) + lookAtPoint[2];
}

void Camera::calculateLeftVector()
{
	up[0] = 0.0;
	up[1] = 1.0;
	up[2] = 0.0;
	
	leftVector[0] = -lookAt[1]*up[2] + lookAt[2]*up[1];
	leftVector[1] = -lookAt[2]*up[0] + lookAt[0]*up[2];
	leftVector[2] = -lookAt[0]*up[1] + lookAt[1]*up[0];

	float magnitude = sqrtf(leftVector[0] * leftVector[0] + leftVector[1] * leftVector[1] + leftVector[2] * leftVector[2]);

	leftVector[0] /= magnitude;
	leftVector[1] /= magnitude;
	leftVector[2] /= magnitude;

}

void Camera::calculateUp()
{
	up[0] = lookAt[1]*leftVector[2] - lookAt[2]*leftVector[1];
	up[1] = lookAt[2]*leftVector[0] - lookAt[0]*leftVector[2];
	up[2] = lookAt[0]*leftVector[1] - lookAt[1]*leftVector[0];

	float magnitude = sqrtf(up[0] * up[0] + up[1] * up[1] + up[2] * up[2]);
	//I can always make this equal to a preset and then change the field of view based on the planet
	up[0] /= magnitude;
	up[1] /= magnitude;
	up[2] /= magnitude;
}

void Camera::changeFocus(double X, double Y, double Z, double offset)
{
	lookAtPoint[0] = X;
	lookAtPoint[1] = Y;
	lookAtPoint[2] = Z;
	radiusOffset = offset;
}

void Camera::calculateVectors()
{
	calculateTranslation();
	calculateLookAt();
	calculateLeftVector();
	calculateUp();
}

bool Camera::getLockOn()
{
	return lockOn;
}

void Camera::increaseOffset()
{
	radiusOffsetNew+=5;
}

void Camera::decreaseOffset()
{
	radiusOffsetNew-=10;
}

void Camera::resetOffset()
{
	radiusOffsetNew = 10;
}